home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / shadow-3.1.4 / utmp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-05  |  6.7 KB  |  311 lines

  1. /*
  2.  * Copyright 1989, 1990, 1991, 1992, John F. Haugh II
  3.  * All rights reserved.
  4.  *
  5.  * Permission is granted to copy and create derivative works for any
  6.  * non-commercial purpose, provided this copyright notice is preserved
  7.  * in all copies of source code, or included in human readable form
  8.  * and conspicuously displayed on all copies of object code or
  9.  * distribution media.
  10.  */
  11.  
  12. #include <sys/types.h>
  13. #include <utmp.h>
  14. #include <fcntl.h>
  15. #ifndef    BSD
  16. #include <string.h>
  17. #include <memory.h>
  18. #define    bzero(a,n)    memset(a, 0, n)
  19. #else
  20. #include <strings.h>
  21. #define    strchr    index
  22. #define    strrchr    rindex
  23. #endif
  24. #include <stdio.h>
  25. #ifdef    STDLIB_H
  26. #include <stdlib.h>
  27. #endif
  28. #ifdef    UNISTD_H
  29. #include <unistd.h>
  30. #endif
  31. #include "config.h"
  32.  
  33. #ifndef    UTMP_FILE
  34. #define    UTMP_FILE    "/etc/utmp"
  35. #endif
  36.  
  37. #if defined(SUN) || defined(BSD) || defined(SUN4)
  38. #ifndef    WTMP_FILE
  39. #define WTMP_FILE "/usr/adm/wtmp"
  40. #endif
  41. #endif    /* SUN || BSD */
  42.  
  43. #ifndef    lint
  44. static    char    sccsid[] = "@(#)utmp.c    3.15    23:57:02    3/7/92";
  45. #endif
  46.  
  47. extern    struct    utmp    utent;
  48.  
  49. extern    struct    utmp    *getutent();
  50. extern    struct    utmp    *getutline();
  51. extern    void    setutent();
  52. extern    void    endutent();
  53. extern    time_t    time();
  54. extern    char    *ttyname();
  55. extern    long    lseek();
  56.  
  57. #define    NO_UTENT \
  58.     "No utmp entry.  You must exec \"login\" from the lowest level \"sh\""
  59. #define    NO_TTY \
  60.     "Unable to determine your tty name."
  61.  
  62. /*
  63.  * checkutmp - see if utmp file is correct for this process
  64.  *
  65.  *    System V is very picky about the contents of the utmp file
  66.  *    and requires that a slot for the current process exist.
  67.  *    The utmp file is scanned for an entry with the same process
  68.  *    ID.  If no entry exists the process exits with a message.
  69.  *
  70.  *    The "picky" flag is for network and other logins that may
  71.  *    use special flags.  It allows the pid checks to be overridden.
  72.  *    This means that getty should never invoke login with any
  73.  *    command line flags.
  74.  */
  75.  
  76. void
  77. checkutmp (picky)
  78. int    picky;
  79. {
  80.     char    *line;
  81. #ifdef    USG
  82.     struct    utmp    *ut;
  83. #ifndef    NDEBUG
  84.     int    pid = getppid ();
  85. #else
  86.     int    pid = getpid ();
  87. #endif
  88. #endif
  89.  
  90. #if !defined(SUN) && !defined(SUN4)
  91.     setutent ();
  92. #endif    /* SUN */
  93.  
  94. #ifdef    USG
  95.     if (picky) {
  96.         while (ut = getutent ())
  97.             if (ut->ut_pid == pid)
  98.                 break;
  99.  
  100.         if (ut)
  101.             utent = *ut;
  102.  
  103.         endutent ();
  104.  
  105.         if (! ut) {
  106.              (void) puts (NO_UTENT);
  107.             exit (1);
  108.         }
  109. #ifndef    UNIXPC
  110.  
  111.         /*
  112.          * If there is no ut_line value in this record, fill
  113.          * it in by getting the TTY name and stuffing it in
  114.          * the structure.  The UNIX/PC is broken in this regard
  115.          * and needs help ...
  116.          */
  117.  
  118.         if (utent.ut_line[0] == '\0')
  119. #endif
  120.         {
  121.             if (! (line = ttyname (0))) {
  122.                 (void) puts (NO_TTY);
  123.                 exit (1);
  124.             }
  125.             if (strncmp (line, "/dev/", 5) == 0)
  126.                 line += 5;
  127.             (void) strncpy (utent.ut_line, line,
  128.                     (int) sizeof utent.ut_line);
  129.         }
  130.     } else {
  131.         if (! (line = ttyname (0))) {
  132.             puts (NO_TTY);
  133.             exit (1);
  134.         }
  135.         if (strncmp (line, "/dev/", 5) == 0)
  136.             line += 5;
  137.  
  138.          (void) strncpy (utent.ut_line, line,
  139.                           (int) sizeof utent.ut_line);
  140.         if (ut = getutline (&utent))
  141.              (void) strncpy (utent.ut_id, ut->ut_id,
  142.                      (int) sizeof ut->ut_id);
  143.  
  144.         (void) strcpy (utent.ut_user, "LOGIN");
  145.         utent.ut_pid = getpid ();
  146.         utent.ut_type = LOGIN_PROCESS;
  147.         (void) time (&utent.ut_time);
  148.     }
  149. #else    /* !USG */
  150.  
  151.     /*
  152.      * Hand-craft a new utmp entry.
  153.      */
  154.  
  155.     bzero (&utent, sizeof utent);
  156.     if (! (line = ttyname (0))) {
  157.         puts (NO_TTY);
  158.         exit (1);
  159.     }
  160.     if (strncmp (line, "/dev/", 5) == 0)
  161.         line += 5;
  162.  
  163.     (void) strncpy (utent.ut_line, line, sizeof utent.ut_line);
  164.     (void) time (&utent.ut_time);
  165. #endif    /* !USG */
  166. }
  167.  
  168. /*
  169.  * setutmp - put a USER_PROCESS entry in the utmp file
  170.  *
  171.  *    setutmp changes the type of the current utmp entry to
  172.  *    USER_PROCESS.  the wtmp file will be updated as well.
  173.  */
  174.  
  175. void
  176. setutmp (name, line)
  177. char    *name;
  178. char    *line;
  179. {
  180. #ifdef SVR4
  181.     struct    utmp    utmp;
  182.     struct    utmpx    *utmpx, utxline;
  183.     extern int gettimeofday (struct timeval *tp);
  184.  
  185.     /*
  186.      * Update utmpx.  We create an empty entry in case there is
  187.      * no matching entry in the utmpx file.
  188.      */
  189.  
  190.     utmpxname (UTMPX_FILE);
  191.     memset (&utxline, 0, sizeof utxline);
  192.     strncpy (utxline.ut_line, line, sizeof utxline.ut_line);
  193.     utmpx = getutxline (&utxline);
  194.  
  195.     if (!utmpx)
  196.         utmpx = &utxline;
  197.  
  198.     /*
  199.      * Fill in the fields in the utmpx entry and write it out.
  200.      */
  201.  
  202.     strncpy (utmpx->ut_user, name, sizeof utmpx->ut_user);
  203.     utmpx->ut_pid = getpid ();
  204.     utmpx->ut_type = USER_PROCESS;
  205.     gettimeofday (&(utmpx->ut_tv));
  206.  
  207.     pututxline (utmpx);
  208.  
  209.     /*
  210.      * Now fill-in the regular utmp file entry.  All the information
  211.      * it needs is in utmpx.  We scribble it out as well.
  212.      */
  213.  
  214.     utmpname (UTMP_FILE);
  215.     getutmp (utmpx, &utmp);
  216.     pututline (&utmp);
  217.     endutent ();
  218.  
  219.     /* 
  220.      * Update the WTMP and WTMPX files and end access to UTMPX.  The
  221.      * endutxent() can't be done until now since utmpx is still needed
  222.      * and endutext() trashes the contents.
  223.      */
  224.  
  225.     updwtmpx(WTMPX_FILE, utmpx);
  226.     endutxent();
  227.  
  228.      utent = utmp;
  229. #else /* !SVR4 */
  230.     struct    utmp    utmp;
  231.     int    fd;
  232.     int    found = 0;
  233.  
  234.     if (! (fd = open (UTMP_FILE, O_RDWR)))
  235.         return;
  236.  
  237. #if !defined(SUN) && !defined(BSD) && !defined(SUN4)
  238.      while (! found && read (fd, &utmp, sizeof utmp) == sizeof utmp) {
  239.          if (! strncmp (line, utmp.ut_line, (int) sizeof utmp.ut_line))
  240.             found++;
  241.     }
  242. #endif
  243.     if (! found) {
  244.  
  245.         /*
  246.          * This is a brand-new entry.  Clear it out and fill it in
  247.          * later.
  248.          */
  249.  
  250.           (void) bzero (&utmp, sizeof utmp);
  251.          (void) strncpy (utmp.ut_line, line, (int) sizeof utmp.ut_line);
  252.     }
  253.  
  254.     /*
  255.      * Fill in the parts of the UTMP entry.  BSD has just the name,
  256.      * while System V has the name, PID and a type.
  257.      */
  258.  
  259. #if defined(SUN) || defined(BSD) || defined(SUN4)
  260.     (void) strncpy (utmp.ut_name, name, (int) sizeof utent.ut_name);
  261. #else    /* SUN */
  262.      (void) strncpy (utmp.ut_user, name, (int) sizeof utent.ut_user);
  263.     utmp.ut_type = USER_PROCESS;
  264.     utmp.ut_pid = getpid ();
  265. #endif    /* SUN || BSD */
  266.  
  267.     /*
  268.      * Put in the current time (common to everyone)
  269.      */
  270.  
  271.     (void) time (&utmp.ut_time);
  272.  
  273. #ifdef UT_HOST
  274.     /*
  275.      * Update the host name field for systems with networking support
  276.      */
  277.  
  278.     (void) strncpy (utmp.ut_host, utent.ut_host, (int) sizeof utmp.ut_host);
  279. #endif
  280.  
  281.     /*
  282.      * Locate the correct position in the UTMP file for this
  283.      * entry.
  284.      */
  285.  
  286. #if defined(SUN) || defined(BSD) || defined(SUN4)
  287.     (void) lseek (fd, (long) (sizeof utmp) * ttyslot (), 0);
  288. #else
  289.     if (found)    /* Back up a splot */
  290.         lseek (fd, (long) - sizeof utmp, 1);
  291.     else        /* Otherwise, go to the end of the file */
  292.         lseek (fd, (long) 0, 2);
  293. #endif
  294.  
  295.     /*
  296.      * Scribble out the new entry and close the file.  We're done
  297.      * with UTMP, next we do WTMP (which is real easy, put it on
  298.      * the end of the file.
  299.      */
  300.  
  301.     (void) write (fd, &utmp, sizeof utmp);
  302.     (void) close (fd);
  303.  
  304.     if ((fd = open (WTMP_FILE, O_WRONLY|O_APPEND)) >= 0) {
  305.         (void) write (fd, &utmp, sizeof utmp);
  306.         (void) close (fd);
  307.     }
  308.      utent = utmp;
  309. #endif /* SVR4 */
  310. }
  311.